#include<iostream>
#include<WinSock2.h>
#include <thread>
#include<string>
#include <time.h>
#include<fstream>

#pragma warning(disable:4996)
#pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll
using namespace std;

const int MAXBUF = 1024;
const double TIMEOUT = 5 * CLOCKS_PER_SEC;
#define SYN 4
#define ACK 2
#define FIN 1
#define ACK_SYN 6
#define ACK_FIN 3
#define OVER 5

struct HEADER {
	u_short len = 0;//2
	u_short ck_sum = 0;//2
	u_short flag = 0;//[SYN ACK FIN]	//2
	unsigned char seq_num = 0;//1
	unsigned char ack_num = 0;//1
}head;
u_short cksum(u_short* mes, int count) {//u_short宏定义为short类型，占2个字节；以16位为单位取报文(mes) 
	//mes指向报文，count表示报文-16位 为单位的组数
	u_long sum = 0;
	while (count--) {
		sum += *mes++;//以16位为单位累加
		if (sum & 0xffff0000) {//如果超出了两个字节，说明有溢出
			sum &= 0xffff;//只保留低两个字节
			sum++;
		}
	}
	return ~(sum & 0xffff);
}
void shake(SOCKET sock, SOCKADDR* sockAddr) {//三次握手
	//socket, 缓冲区，大小，NULL
	//第一次握手
	u_long mode = 1;
	ioctlsocket(sock, FIONBIO, &mode);
	int len = sizeof(sockAddr);
	head.len = 8;//8个字节
	head.flag = SYN;
	srand((unsigned)time(NULL));
	head.seq_num = rand() % (MAXBYTE);//产生随机序列号
	cout << "第一次握手产生的Seq序列号为：" << (int)head.seq_num << endl;
	head.ack_num = 0;
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);

	char* buf = new char[head.len];
	memcpy(buf, &head, head.len);
	clock_t start;

	while (sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {
		cout << "send发送失败！重新发送..." << endl;
		cout << "5s后重新发送..." << endl;
		Sleep(5000);
	}
	cout << "等待第二次握手中....." << endl;
	start = clock();
	//接收第二次握手


	while (1) {
		if (clock() - start > TIMEOUT) {
			cout << "超时...重传中..." << endl;
			while (sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {
				cout << "send发送失败！重新发送..." << endl;
			}
			cout << "等待第二次握手中....." << endl;
			start = clock();
		}
		else {
			//recv(sock, buf, 8, 0);
			recvfrom(sock, buf, 8, 0, (sockaddr*)&sockAddr, (&len));
			HEADER* recv_head = (HEADER*)buf;
			if (cksum((u_short*)buf, 4) != 0xffff) {
				cout << "error!传输错误" << endl;//等待重传
			}
			else {
				if (recv_head->flag == ACK_SYN) {
					cout << "成功接收第二次握手内容!" << endl;
					cout << "第二次握手中Ack为" << (int)recv_head->ack_num << endl;
					cout << "第二次握手中Seq为" << (int)recv_head->seq_num << endl;
					break;
				}
			}
		}
	}
	//发送第三次握手内容
	head.len = 8;//8个字节
	head.flag = SYN;
	srand((unsigned)time(NULL));
	head.seq_num = rand() % (MAXBYTE);//产生随机序列号
	head.ack_num = 0;
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);

	memcpy(buf, &head, head.len);
	while (sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {
		cout << "send发送失败！重新发送..." << endl;
	}
	cout << "第三次握手已发送.....可以进行数据传输..." << endl;
	// 	   0008 FFE6 0004 0D 00
	//while(send(sock))

}
int main() {
	cout << "客户端" << endl;
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);//希望用户使用2.2版本的Socket
	SOCKET sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);


	struct sockaddr_in sockAddr;//sockaddr_in用作定义，socketaddr用作函数参数
	memset(&sockAddr, 0, sizeof(sockAddr));  //将结构体清零
	sockAddr.sin_family = PF_INET;//TCP
	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");//指定服务器IP
	sockAddr.sin_port = htons(1234);//指定服务器端口
	//shake(sock, (SOCKADDR*)&sockAddr);

	//-----------------------------三次握手-----------------------------
	int len = sizeof(sockAddr);
	head.len = 8;//8个字节
	head.flag = SYN;
	srand((unsigned)time(NULL));
	head.seq_num = rand() % (MAXBYTE);//产生随机序列号
	cout << "第一次握手的Seq序列号为：" << (int)head.seq_num << endl;
	cout << "第一次握手的Ack序列号为：" << (int)head.ack_num << endl;
	head.ack_num = 0;
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);

	char* buf = new char[head.len];
	memcpy(buf, &head, head.len);
	clock_t start;

	sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));

	cout << endl << "等待第二次握手中....." << endl;
	start = clock();
	//接收第二次握手
	HEADER* recv_head;
	u_long mode = 1;//非阻塞，否则recv函数会一直等待
	ioctlsocket(sock, FIONBIO, &mode);
	while (1) {
		if (clock() - start > TIMEOUT) {
			cout << "超时...重传中..." << endl;
			sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
			cout << endl << "等待第二次握手中....." << endl;
			start = clock();
		}
		else {
			recvfrom(sock, buf, 8, 0, (sockaddr*)&sockAddr, (&len));
			recv_head = (HEADER*)buf;
			if (cksum((u_short*)buf, 4) != 0x0000) {
				cout << "error!第二次握手传输中出现错误！" << endl;//等待重传
			}
			else {
				if (recv_head->flag == ACK_SYN) {
					cout << "成功接收第二次握手内容!" << endl;
					cout << "第二次握手中Ack为" << (int)recv_head->ack_num << endl;
					cout << "第二次握手中Seq为" << (int)recv_head->seq_num << endl;
					break;
				}
			}
		}
	}
	//发送第三次握手内容
	cout << endl << "进行第三次握手:" << endl;

	head.flag = ACK;
	srand((unsigned)time(NULL));
	head.seq_num = recv_head->ack_num;//产生随机序列号
	head.ack_num = recv_head->seq_num + 1;
	cout << "第三次握手中Ack为" << (int)recv_head->ack_num << endl;
	cout << "第三次握手中Seq为" << (int)recv_head->seq_num << endl;

	char filename[50] = { 0 };
	cout << "请输入待传输文件名称:";
	cin >> filename;
	//filename = "1.jpg";

	head.len = sizeof(HEADER) + strlen(filename);//数据包大小
	head.ck_sum = 0;
	memcpy(buf, &head, sizeof(HEADER));
	memcpy(buf + sizeof(HEADER), &filename, strlen(filename));
	head.ck_sum = cksum((u_short*)buf, head.len / 2 + head.len % 2);
	memcpy(buf, &head, sizeof(HEADER));
	//cout << "len:" << head.len << endl;
	//cout << "sum=" << cksum((u_short*)buf, head.len / 2 + head.len % 2) << endl;

	while (sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {
		cout << "send发送失败！重新发送..." << endl;
	}
	cout << "第三次握手已发送.....可以进行数据传输..." << endl;

	//-----------------------------三次握手-----------------------------
	// 
	// 
	//-----------------------------传输数据-----------------------------

	ifstream f_send;
	bool type = 0;//表示文本
	if (strcmp(&filename[strlen(filename) - 3], "jpg")) {//文本文件
		f_send.open(filename, ios::in);
	}
	else {
		f_send.open(filename, ios::binary);
		type = 1;//表示图片
	}
	if (!f_send.is_open()) {
		cout << "File does not exist. " << endl;
		return 0;
	}
	//计算文件大小
	f_send.seekg(0, f_send.end);
	int pic_length = f_send.tellg();
	f_send.seekg(0, f_send.beg);


	int pkg_num = pic_length / MAXBUF + (pic_length % MAXBUF == 0);
	cout << "pkg_num:" << pkg_num << endl;
	char* buff = new char[MAXBUF + sizeof(HEADER)];
	char* buffer = new char[MAXBUF + 1];

	head.seq_num = rand() % (MAXBYTE);//第一个包产生随机序列号
	head.ack_num = 0;
	head.len = MAXBUF + sizeof(HEADER);
	head.flag = ACK;
	srand((unsigned)time(NULL));
	cout << endl << "数据发送中..." << endl;
	clock_t start_send = clock();
	for (int i = 0; i < pkg_num; i++) {
		f_send.seekg(i * MAXBUF, std::ios::beg);
		f_send.read(buffer, MAXBUF);//读取文件内容，存入buffer

		head.ck_sum = 0;
		memset(buff, 0, MAXBUF + sizeof(HEADER));
		memcpy(buff, &head, sizeof(HEADER));
		memcpy(buff + sizeof(HEADER), buffer, MAXBUF);
		head.ck_sum = cksum((u_short*)buff, head.len / 2 + head.len % 2);
		memcpy(buff, &head, sizeof(HEADER));

		sendto(sock, buff, MAXBUF + sizeof(HEADER), 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
		cout << "Msg size:" << (int)head.len << "bytes! FLAG:" << (int)head.flag << " SEQ:" << (int)head.seq_num << " SUM:" << (int)head.ck_sum << endl;
		start = clock();

		HEADER* recv_head;
		u_long mode = 1;//非阻塞，否则recv函数会一直等待
		ioctlsocket(sock, FIONBIO, &mode);
		while (1) {
			if (clock() - start > TIMEOUT) {
				cout << "超时...重传Seq=" << (int)head.seq_num << "的数据包中..." << endl;
				sendto(sock, buff, MAXBUF + sizeof(HEADER), 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
				start = clock();
			}
			else {
				recvfrom(sock, buffer, 8, 0, (sockaddr*)&sockAddr, (&len));//收到信息
				recv_head = (HEADER*)buffer;
				if (cksum((u_short*)buffer, 4) != 0x0000 || recv_head->ack_num != ((int)head.seq_num + 1) % 256) {
					//cout << "error!Seq=" << (int)head.seq_num << "的传输中出现错误！" << endl;//等待重传
				}
				else {
					if (recv_head->flag == ACK) {
						if (head.seq_num == 255) {
							head.seq_num = 0;
						}
						else {
							head.seq_num++;
						}
						start = clock();
						break;//发下一个包
					}
				}
			}
		}
	}
	f_send.close();
	clock_t end_send = clock();
	cout << endl << "传输完成！！" << endl;
	cout << "传输总时间为:" << (double)((end_send - start_send) / CLOCKS_PER_SEC) << "s" << endl;
	cout << "吞吐率为:" << ((float)pic_length) / ((end_send - start_send) / CLOCKS_PER_SEC) << "byte/s" << endl;
	//-----------------------------传输数据-----------------------------
	// 
	// 
	//-----------------------------四次挥手-----------------------------
	head.len = 8;//8个字节
	head.flag = ACK_FIN;
	srand((unsigned)time(NULL));
	head.seq_num = rand() % (MAXBYTE);//产生随机序列号
	unsigned char store_seq = head.seq_num;//保存这个seq值
	head.ack_num = rand() % (MAXBYTE);
	cout << endl << "第一次挥手的Seq序列号为：" << (int)head.seq_num << endl;
	cout << "第一次挥手的Ack序列号为：" << (int)head.ack_num << endl;
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);
	memset(buf, 0, strlen(buf));
	memcpy(buf, &head, head.len);
	sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));//第一次挥手BYEBYE~
	start = clock();

	while (1) {
		if (clock() - start > TIMEOUT) {
			cout << "超时...重传第一次挥手中..." << endl;
			sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));//第一次挥手BYEBYE~
			start = clock();
		}
		else {
			recvfrom(sock, buffer, 8, 0, (sockaddr*)&sockAddr, (&len));
			recv_head = (HEADER*)buffer;
			if (cksum((u_short*)buffer, 4) != 0x0000) {
				cout << "error!第二次挥手中出现错误！" << endl;//等待重传
			}
			else {
				if (recv_head->flag == ACK && recv_head->ack_num == ((int)head.seq_num + 1) % 256 && recv_head->seq_num == head.ack_num) {
					cout << endl << "成功进行第二次挥手!" << endl;
					cout << "第二次挥手接收到的ack:" << (int)recv_head->ack_num << endl;
					cout << "第二次挥手接收到的seq:" << (int)recv_head->seq_num << endl;
					break;//发下一个包
				}
			}
		}
	}

	recvfrom(sock, buffer, 8, 0, (sockaddr*)&sockAddr, (&len));
	recv_head = (HEADER*)buffer;
	if (recv_head->flag == ACK_FIN) {
		cout << endl << "成功进行第三次挥手..." << endl;
		cout << "第三次挥手接收到的ack:" << (int)recv_head->ack_num << endl;
		cout << "第三次挥手接收到的seq:" << (int)recv_head->seq_num << endl;
	}

	head.len = 8;//8个字节
	head.flag = ACK;
	head.seq_num = recv_head->ack_num;
	head.ack_num = recv_head->seq_num + 1;
	cout << endl << "第四次挥手的Seq序列号为：" << (int)head.seq_num << endl;
	cout << "第四次挥手的Ack序列号为：" << (int)head.ack_num << endl;
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);
	memset(buf, 0, strlen(buf));
	memcpy(buf, &head, head.len);
	sendto(sock, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));//第一次挥手BYEBYE~

	closesocket(sock);
	WSACleanup();
	return 0;
}
